#include "javawriter.h"

JavaWriter::JavaWriter()
{
}

void JavaWriter::run()
{
    // save dir
    QDir dir(this->_filePath);

    // creating project dir
    qDebug() << this->_project->name();
    if (!dir.mkdir(this->_project->name()) && !dir.exists()) {
        return;
    }

    // changing into new dir
    dir.cd(this->_project->name());

    // writing items
    this->writeDir(this->_project->umlItemRoot(), &dir);

}

void JavaWriter::writeDir(UmlDirItem *dir, QDir *filePath)
{
    QByteArray blueJ = "#BlueJ package file\n";
    blueJ += "package.showExtends=true\n";
    blueJ += "package.showUses=true\n";
    int count = 1;

    foreach(UmlGraphicsItem *item, dir->items()) {

        // creating sub dir
        if (item->isOfType(UmlItem::UmlPackageItemType)) {
            UmlDirItem *dir = static_cast<UmlDirItem*>(item);

            filePath->mkdir(dir->name());
            filePath->cd(dir->name());

            this->writeDir(dir, filePath);
        }

        // writing class
        if (item->isOfType(UmlItem::UmlClassItemType)) {
            UmlClassItem *classItem = static_cast<UmlClassItem*>(item);

            this->writeClass(classItem, filePath);

            QString blueJPrefix = QString("target%1.").arg(count);
            blueJ += blueJPrefix + QString("name=%1\n").arg(classItem->name());
            blueJ += blueJPrefix + "type=ClassTarget\n";
            blueJ += blueJPrefix + QString("x=%1\n").arg(classItem->pos().x());
            blueJ += blueJPrefix + QString("y=%1\n").arg(classItem->pos().y());

            count++;
        }

    }

    QFile blueJFile(filePath->path() + "/package.bluej");
    blueJFile.open(QIODevice::WriteOnly);
    blueJFile.write(blueJ);
    blueJFile.close();
}

void JavaWriter::writeClass(UmlClassItem *classItem, QDir *filePath)
{
    // setting filename
    QString fileName = QString("%1.java").arg(classItem->name());

    // creating file
    QFile file(filePath->path() + "/" + fileName);
    QByteArray content = "";

    // abstract keyword
    if (classItem->isAbstract()) {
        content += "public abstract ";
    }

    else if (classItem->isInterface()) {
        content += "interface ";
    }

    else {
        content += "public class ";
    }

    content += classItem->name();

    // extends
    if (!classItem->inherits().isEmpty()) {

        content += " extends ";

        QListIterator<UmlClassItem*> iter(classItem->inherits());
        while(iter.hasNext()) {
            content += iter.next()->name();
            if (iter.hasNext()) {
                content += ", ";
            }
        }
    }

    // implements
    if (!classItem->implements().isEmpty()) {

        content += " implements ";

        QListIterator<UmlClassItem*> iter(classItem->implements());
        while(iter.hasNext()) {
            content += iter.next()->name();
            if (iter.hasNext()) {
                content += ", ";
            }
        }
    }

    content += " {\n\n";

    this->writeClassAttributes(classItem, &content);
    this->writeClassMethod(classItem, &content);

    content +=  "}";

    file.open(QIODevice::WriteOnly);
    file.write(content);
    file.close();
}

void JavaWriter::writeClassAttributes(UmlClassItem *classItem, QByteArray *content)
{
    if (!classItem->hasAttributes()) {
        return;
    }

    foreach(ClassAttribute *att, classItem->attList()) {
        content->append("\t" + att->visibilityToString() + " " + att->returnType() + " " + att->name() + ";\n\n");
    }
}

void JavaWriter::writeClassMethod(UmlClassItem *classItem, QByteArray *content)
{
    if (!classItem->hasMethods()) {
        return;
    }

    foreach (ClassMethod *meth, classItem->methList()) {
        content->append("\t" + meth->visibilityToString() + " " + meth->returnType() + " " + meth->name() + "(");

        if (meth->hasArguments()) {
            QListIterator<ClassAttribute*> iter(meth->argList());
            while (iter.hasNext()) {
                ClassAttribute *att = iter.next();
                content->append(att->returnType() + " " + att->name());
                if (iter.hasNext()) {
                    content->append(", ");
                }
            }
        }

        content->append(") {\n");
        content->append("\t\t // Implementierung\n");
        content->append("\t}\n\n");
    }
}
